﻿class TestBase {
    suiteName: string = 'Not specified';

    childSuites: Array<TestBase> = [];

    beforeEach(): void {
    }
    afterEach(): void {
    }

    run(): void {
        describe(this.suiteName, () => {
            beforeEach(() => {
                this.beforeEach();
            });

            var target: any = this;
            for (var m in target) {
                if (m.length < 6)
                    continue;

                if (m.substr(0, 5) == 'test_') {
                    this.runTest(target, m);
                }
                else if (m.substr(0, 6) == 'async_') {
                    this.runAsyncTest(target, m);
                }
            }

            for (var i in this.childSuites) {
                this.childSuites[i].run();
            }

            afterEach(() => {
                this.afterEach();
            });

        });

    }

    private runTest(target: any, method: string) {
        it(method.substr(5), () => {
            target[method].apply(target);
        });

    }

    private runAsyncTest(target: any, method: string) {
        var test = target[method].apply(target);

        if (typeof test == 'function')
            test = new AsyncTestBase(test);

        test.run(method.substr(6));
    }


}

class AsyncTestBase {
    private _test: { (notify: { (): void }): void };
    constructor(test: { (notify: { (): void }): { (): void } }) {
        this._test = test;
    }

    run(name): void {
        var test = this._test; 
       describe('Async', () => {
            //beforeEach(() => this._test());
            beforeEach(() => {
                //(<any>jasmine).DEFAULT_TIMEOUT_INTERVAL = 10000;
            });

            var _validate;
            it(name, (done) => {
                _validate = test(() => {
                    _validate();
                    done();
                });
            });

            //afterEach(() => {
            //    if (typeof _validate != 'undefined')
            //        _validate()
            //});
        });
    }
}